<?php
/**
	* Copyright (c) 2009, Fabio Kreusch
	*
	* Licensed under The MIT License
	* Redistributions of files must retain the above copyright notice.
	* @copyright            Copyright (c) 2009, Fabio Kreusch
	* @link                 fabio.kreusch.com.br
	* @license              http://www.opensource.org/licenses/mit-license.php The MIT License
*/
class SubscriptionsController extends NewsletterAppController {
	var $name = 'Subscriptions';
	var $uses = array('Newsletter.Group', 'Newsletter.Subscription');
	var $helpers = array('Time');

	var $paginate = array(
	'Subscription' => array(
		'limit' => 40,
		'order' => array('Subscription.email' => 'asc')
		)
		);

	function beforeFilter() {
		parent::beforeFilter();
		//$this->Auth->allow('unsubscribe', 'subscribe', 'confirm_subscription');
	}

	#Public

	function unsubscribe() {
		$message = __('Enter your email to remove yourself from the subscriber list.', true);
		if(!empty($this->data)) {
			$subscribed = $this->Subscription->find('first', array('conditions' => array('email' => $this->data['Subscription']['email'], 'opt_out_date' => null)));
			if($subscribed) {
				$this->Subscription->id = $subscribed['Subscription']['id'];
				if( $this->Subscription->saveField('opt_out_date', date('Y-m-d H:i:s')) ) {
					#send email
					$subject = Configure::read('Newsletter.unsubscribe_subject');
					if(!$subject) { 
						$subject = __('Unsubscribe Confirmation', false); 
					}
					$message = Configure::read('Newsletter.mail_opt_out_message');
					if(!$message) { 
						$message = __('Your email has been removed from the list!', false); 
					}

					$subscription = $this->Subscription->read(); 
					$this->set('name', $subscription['Subscription']['name']);
					$this->sendEmail($subject, 'unsubscribe', $subscription['Subscription']['email']);
				}
			} else {
				$message = Configure::read('Newsletter.unsubscribe_not_found_site_message');
				if(!$message) {
					$message = __('Email not in subscription list', true);
				}
			}
		}
		$this->_echomessage($message);
	}

	function subscribe() {
		$message = __('Enter your email to add yourself to the subscriber list.', true);
		if(!empty($this->data)) {
			$subscribed = $this->Subscription->findByEmail($this->data['Subscription']['email']);

			#if the email isn't yet registered or if it already exists but is into opt_out or it's waiting for confirmation, 
			#save and set the user confirmation code and send email, otherwise tell the user he already is opt_in
			if(empty($subscribed) || !empty($subscribed['Subscription']['opt_out_date']) || !empty($subscribed['Subscription']['confirmation_code']) ) {

				if(!empty($subscribed)) {
					$this->data['Subscription']['id'] = $subscribed['Subscription']['id'];
				} else {
					$this->Subscription->create();
					if(empty($this->data['Subscription']['name'])) {
						if( $matches = preg_match("/([^@]+)/si", $this->data['Subscription']['email']) ) {
							$this->data['Subscription']['name'] = $matches[0];
						} else {
							$this->data['Subscription']['name'] = __("No name", true);
						}
						
					}
				}

				$confirmation_code = md5(date('Y-m-d H:i:s').$this->data['Subscription']['email']);
				$this->data['Subscription']['confirmation_code'] = $confirmation_code;
				//$this->Subscription->set();
				if($this->Subscription->save($this->data)) {
					#adds subscription to default site_group
					$site_group = Configure::read('Newsletter.siteGroup');

					if(!$site_group) {$site_group = '1';}
					$this->Subscription->habtmAdd('Group', $this->Subscription->id, $site_group);

					#send email
					$subject = Configure::read('Newsletter.subscribe_subject');
					if(!$subject) { $subject = __('Subscription Confirmation', true); }

					$subscription = $this->Subscription->read(null, $this->Subscription->id);
					$this->set('name', $subscription['Subscription']['name']);
					$this->set('confirmation_code', $subscription['Subscription']['confirmation_code']);
					//$this->set('url', Configure::read('Newsletter.confirm_url'));
					$this->sendEmail($subject, 'subscribe', $subscription['Subscription']['email']);  

					$message = Configure::read('Newsletter.subscribe_site_message');
					if(!$message) {$message = __('A confirmation message was sent to your email', true);}

				} else {
					$message = __('Your email could not be saved. Please, try again.', true);
				}


			} else {
				$message = Configure::read('Newsletter.subscribe_already_in_list');
				if(!$message) {$message = __('The requested email is already into the list', true);}

			}
		} 
		$this->_echomessage($message);
	}

	function confirm_subscription($id) {
		$subscribed = $this->Subscription->findByConfirmationCode($id);

		if(!empty($id) && !empty($subscribed)) {
			$this->Subscription->set($subscribed);
			$this->Subscription->saveField('opt_out_date', null);
			$this->Subscription->saveField('confirmation_code', null);

			$this->set('subscribed', $subscribed);

			$message = Configure::read('Newsletter.subscribe_confirmation');
			if(!$message) {$message = __('Subscription confirmed', true);}
		} else {
			$message = Configure::read('Newsletter.subscribe_confirmation_invalid');
			if(!$message) {$message = __('Invalid confirmation code', true);}
		}
		$this->_echomessage($message);
	} 
	function _echomessage($message) {
		$this->Session->setFlash($message);
		$this->set('message', $message);
	} 

	#Admin

	function admin_index() {
		$conditions = null;

		if($this->isNotEmpty('Filter.value')) {
			$filter = $this->data['Filter']['value'];
			$conditions = array('OR' => array(
				'Subscription.name LIKE' => '%'.$filter.'%',
				'Subscription.email LIKE' => '%'.$filter.'%',
				)
				);
		}
		$this->set('subscriptions', $this -> paginate('Subscription', $conditions));
		$this->set('groups', $this->Group->find('list'));
		$this->set('siteGroup', Configure::read('Newsletter.siteGroup'));
	}

	function admin_add() {
		if(!empty($this->data)) {
			$this->Subscription->set($this->data);
			if($this->Subscription->save()) {
				$this->Session->setFlash(__('Subscription successfully added', true));
				$this->redirect(array('action' => 'index'));
			}
		}

		$this->set('siteGroup', Configure::read('Newsletter.siteGroup'));
		$this->set('groups', $this->Group->find('list'));
	}

	function admin_edit($id = null) {
		if(!$id) {
			$this->Session->setFlash(__('Invalid subscription id', true));
			$this->redirect(array('action' => 'index'));
		}

		if( empty($this->data) ) {
			$this->data = $this->Subscription->read(null, $id);
		} else {
			$this->Subscription->set($this->data);
			if( $this->Subscription->save() ) {
				$this->Session->setFlash(__('Subscription successfully saved', true));
			}
		}

		$this->set('groups', $this->Group->find('list'));
	}

	function admin_delete($id) {
		$this->autoRender = false;

		if($this->Subscription->delete($id)) {
			$this->Session->setFlash(__('Subscription deleted', true));
		} else {
			$this->Session->setFlash(__('Deleting failed', true));
		}
		$this->redirect(array('action' => 'index'));
	}

	# TODO tratement for if the admin is in a paginate specific page
	function admin_invert_opt_out($id) {
		$this->Subscription->id = $id;
		$subscribed = $this->Subscription->read();

		if($subscribed['Subscription']['opt_out_date']) {
			$this->Subscription->saveField('opt_out_date', null);
		} else {
			$this->Subscription->saveField('opt_out_date', date('Y-m-d H:i:s'));
		}

		$subscribed = $this->Subscription->read();
		$this->layout = 'clean';
		$this->set('subscription', $subscribed);
	}

	function admin_import_csv() {
		if (!empty($this->data) && is_uploaded_file($this->data['Subscription']['csv']['tmp_name'])) {
			set_time_limit(0);

			$lines = $this->readUploadedCSV($this->data['Subscription']['csv']['tmp_name']);
			$errors = array();
			$data = array();

			foreach($lines as $number => $line) {
				$error = $this->validateCSVLine($line, ($number+1));
				if(count($error)>0) {
					$errors = array_merge($errors, $error);
				} else {
					if(!array_key_exists(1, $line)) {
						$line[1] = '';
					}
					array_push($data, $line);
				}
			}
			$this->Subscription->importCsv($data, $this->data['Group']['Group']);
			$this->set('errors', $errors);

			if(!empty($errors)) {
				$message = "<ul>";
				foreach ($errors as $error) {
					$message .= "<li>$error</li>";        
				}
				$message .= "</ul>";
				$message = __('Data imported, but there where the following errors: ', true).$message;
			} else {
				$message = __('Data imported', true);
			}
			$this->Session->setFlash($message);
			$this->redirect(array('action' => 'index'));
		} else {
			$this->Session->setFlash(__('No data to import', true));
			$this->redirect(array('action' => 'index'));
		}
	}

	/**
		* Reads a CSV file and returns a list with each line.
		* @param $tmp_name The CSV path.
		* @return An array with each line.
		* @access private
		**/
	function readUploadedCSV($tmp_name) {
		$lines = array();

		ini_set('auto_detect_line_endings',1);
		$handle = fopen($tmp_name, "r");
		while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
			array_push($lines,$data);			 
		}
		return $lines;
	}

	/**
		* Validates a csv line, verifying if it has a valid email.
		* @param $list A csv array as returned by _read_uploaded_csv().
		* @return Array with errors, if any. False otherwise.
		* @access true
		**/
	function validateCSVLine($line, $line_number) {
		$errors = array();

		if(!is_array($line)) {
			array_push($errors,'Invalid line');			 
		}

		if($line[0] == null || $line[0] == '') {
			array_push($errors, "Error in line $line_number: blank email");
		} 
		return $errors;
	}
}
?>
